package com.sike.netty.im.common.codc;

import cn.hutool.json.JSONUtil;
import com.sike.netty.im.common.command.Message;
import com.sike.netty.im.common.utils.ProtoBufUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 消息编解码器
 *
 * @author chenssy
 * @date 2023/09/13
 */
@Slf4j
@ChannelHandler.Sharable
public class MessageCodec extends MessageToMessageCodec<ByteBuf, Message> {

    /**
     * 魔数
     */
    private static final int MAGIC_NUMBER = 0x12345678;

    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> out) throws Exception {
        // 获取 ByteBuf 对象
        ByteBuf byteBuf = ctx.alloc().buffer();

        // 1. 4 个字节的魔数
        byteBuf.writeInt(MAGIC_NUMBER);

        // 2. 1 字节的版本
        byteBuf.writeByte(1);

        // 3. 1 字节的序列化方式
        byteBuf.writeByte(0);

        // 消息 head 序列化
        byte[] msgBytes = ProtoBufUtil.serialize(msg);

        // 4. 消息长度
        byteBuf.writeInt(msgBytes.length);

        // 5. 消息内容
        byteBuf.writeBytes(msgBytes);

        out.add(byteBuf);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        // 1. 校验魔数
        int magicNum = msg.readInt();
        if (MAGIC_NUMBER != magicNum) {
            throw new RuntimeException("魔数错误");
        }

        //2. 跳过版本号
        msg.skipBytes(1);
        //3. 跳过序列化方式
        msg.skipBytes(1);

        // 4. 4 字节消息总长度
        int msgLength = msg.readInt();

        // 读取消息
        byte[] bytes = new byte[msgLength];
        msg.readBytes(bytes,0,msgLength);

        // 序列化
        Message message = ProtoBufUtil.deserialize(bytes,Message.class);

        out.add(message);
    }
}
